package ru.vba.context.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import ru.vba.context.FieldContext;
import ru.vba.exceptions.FieldException;
import ru.vba.exceptions.GameException;
import ru.vba.pojo.Bonus;
import ru.vba.pojo.Cell;
import ru.vba.pojo.Coordinate;
import ru.vba.pojo.Point;

public class EruditFieldContext implements FieldContext {
	private List<Point> heap;
	private Random random = new Random();
	private Map<Coordinate, Cell> field ;
	private Map<Coordinate, Bonus> bonuses;
	public EruditFieldContext(int x, int y, List<Point> points, Map<Coordinate, Bonus> bonuses){
		this.heap = points;
		this.bonuses = bonuses;
		buildField(x, y);

	}
	private void buildField(int x, int y){
		field = new HashMap<Coordinate, Cell>();
		for (Long i = 0L; i < x; i++){
			for (Long k = 0L; k < y; k++){
				Coordinate coordinate = new Coordinate();
				coordinate.setPosX(i.intValue());
				coordinate.setPosY(k.intValue());
				field.put(coordinate, null);
			}
		}
	}
	public Cell putCell(Coordinate coordinate, Point point) throws GameException {
		Bonus bonus = bonuses.get(coordinate);
		Cell cell = new Cell(coordinate, bonus, point);

		if (field.get(coordinate) == null){
			field.put(coordinate, cell);
		}else{
			throw new FieldException("coordinate already bound");
		}
		return cell;
	}

	public void addHeap(Point point) {
		heap.add(random.nextInt(heap.size()), point);
	}

	public Point getRandomPoint() throws GameException {
		if (heap.size() > 0){
			int index = random.nextInt(heap.size());
			Point point = heap.get(index);
			heap.remove(index);
			return point;
		}else{
			throw new GameException("size of heap must be greater than 0");
		}
	}


	public boolean isBusy(Coordinate coordinate) {
		return field.get(coordinate) != null;
	}
	public List<Cell> putWord(Map<Coordinate, Point> word) throws GameException {
		List<Cell> result = new ArrayList<Cell>();
		try {
			for (Coordinate coordinate : word.keySet()) {
				Point point = word.get(coordinate);
				Cell cell = putCell(coordinate, point);
				result.add(cell);
			}
		} catch (FieldException e) {
			clearField(new ArrayList<Coordinate>(word.keySet()));
			throw new FieldException(e);
		}
		return result;
	}
	private void clearField(List<Coordinate> coord){
		for (Coordinate coordinate : coord) {
			field.put(coordinate, null);
		}
	}
}
